<?php
/**
 * 
 * nlHelper
 * @author NitraLabs
 *
 */
class nlHelper {

  /**
   * Конвертация строки в массив тегов
   *
   * @static
   * @param  $string
   * @return string
   */
  public static function cleanTag($string) {
    $tag = preg_replace("`[^a-zA-Zа-яёА-ЯЁ0-9 -]`iu", '', $string);
    $tag = trim(rtrim($tag));
    $tag = mb_strtolower($tag, 'UTF-8');

    return $tag;
  }
  
  /**
   * "Cleans" a string in order it to be used as a tag
   * Intended for strings representing a single tag
   *
   * @param      mixed     $tag
   * @return     mixed -> array or the $tag passed as reference...
   */
  public static function convertStringToTags($string) {
    if (is_string($string)) {
      $string = str_replace(',', ' ', $string);
      $string = preg_replace('/[\r\n\s]/u', ' ', $string);
      $string = preg_replace('/\s+/u', ' ', $string);

      $tags = explode(' ', $string);
    } else if (is_array($string)) {
      $tags = $string;
    } else {
      throw new LogicException('No objects allowed here');
    }
    
    $tags = array_map(array('nlHelper', 'cleanTag'), $tags);

    return $tags;
  }

  /**
   * Конвертация числа "float" в письменное представление
   *
   * @static
   * @param float $sum
   * @return string
   */
  public static function convertNumberToMoney($sum) {
     $ret = '';

    // Переводим все еденицы
    if (!self::$converterInitialized && sfConfig::get('sf_i18n')) {
      foreach (array('billions', 'millions', 'thousands', 'hundreds', 'tens', 'tensUnit', 'units', 'unit',  'mant', 'expon') as $var) {
        foreach (self::$$var as $key => &$val) {
          $val = sfContext::getInstance()->getI18N()->__($val);
        }
      }

    }

    self::$converterInitialized = true;

     // имена данных перменных остались от предыдущей версии
     // когда скрипт конвертировал только денежные суммы
     $Kop = 0;
     $Rub = 0;

     $sum = trim($sum);
     // удалим пробелы внутри числа
     $sum = str_replace(' ', '', $sum);

     // флаг отрицательного числа
     $sign = false;
     if($sum[0] == '-')
     {
        $sum = substr($sum, 1);
        $sign = true;
     }

     // заменим запятую на точку, если она есть
     $sum = str_replace(',', '.', $sum);

     $Rub = intval($sum);
     $Kop = round($sum*100 - $Rub*100);

     if($Rub)
     {
        // значение $Rub изменяется внутри функции DescrSot
        // новое значение: $Rub %= 1000000000 для миллиарда
        if($Rub >= 1000000000)
        $ret .= self::DescrSot($Rub, 1000000000, self::$billions ) . ' ';
        if($Rub >= 1000000)
        $ret .= self::DescrSot($Rub, 1000000, self::$millions ) . ' ';
        if($Rub >= 1000)
        $ret .= self::DescrSot($Rub, 1000, self::$thousands, true) . ' ';

        $ret .= self::DescrSot($Rub, 1, self::$mant, true) . ' ';
     }

     if($Kop < 10)
     $ret .= '0';
     $ret .= $Kop . ' ' . self::$expon[ self::DescrIdx($Kop) ];

     // если число было отрицательным добавим минус
     if($sign)
     $ret = '-' . $ret;
     return $ret;
  }

  /**
   *
   * Транслитерация строки
   *
   * @static
   * @param string $string
   * @return string
   */
  public static function transliterate($string) {
    if (preg_match('/[А-Яа-я]/u', $string)) {
      $chars = array(
        "ё" => "yo",
        "ж" => "zh",
        "х" => "kh",
        "ц" => "ts",
        "ч" => "ch",
        "щ" => "sch",
        "щ" => "shch",
        "ш" => "sh",
        "э" => "eh",
        "ю" => "yu",
        "я" => "ya",
        "Ё" => "YO",
        "Ж" => "ZH",
        "Х" => "KH",
        "Ц" => "TS",
        "Ч" => "CH",
        "Щ" => "SCH",
        "Щ" => "SHCH",
        "Ш" => "SH",
        "Э" => "EH",
        "Ю" => "YU",
        "Я" => "YA",
        "ь" => "",
        "а" => "a",
        "б" => "b",
        "в" => "v",
        "г" => "g",
        "д" => "d",
        "е" => "e",
        "з" => "z",
        "и" => "i",
        "й" => "j",
        "к" => "k",
        "л" => "l",
        "м" => "m",
        "н" => "n",
        "о" => "o",
        "п" => "p",
        "р" => "r",
        "с" => "s",
        "т" => "t",
        "у" => "u",
        "ф" => "f",
        "х" => "h",
        "ц" => "c",
        "ы" => "y",
        "Э" => "E",
        "А" => "A",
        "Б" => "B",
        "В" => "V",
        "Г" => "G",
        "Д" => "D",
        "Е" => "E",
        "З" => "Z",
        "И" => "I",
        "Й" => "J",
        "К" => "K",
        "Л" => "L",
        "М" => "M",
        "Н" => "N",
        "О" => "O",
        "П" => "P",
        "Р" => "R",
        "С" => "S",
        "Т" => "T",
        "У" => "U",
        "Ф" => "F",
        "Х" => "H",
        "Ц" => "C",
        "Ы" => "Y",
      );
      $string = strtr($string, $chars);
    }
    return $string;
  }

  /**
   *
   * Транслитерирует строку и вырезает все необычные символы, генерирует slug
   *
   * @static
   * @param string $text
   * @return string
   */
  public static function urlize($text) {
      // Remove all non url friendly characters with the unaccent function
      $text = self::transliterate($text);
      if (function_exists('mb_strtolower')) {
          $text = mb_strtolower($text);
      } else {
          $text = strtolower($text);
      }

      // Remove all none word characters
      $text = preg_replace('/\W/', ' ', $text);

      // More stripping. Replace spaces with dashes
      $text = strtolower(preg_replace('/[^A-Z^a-z^0-9^\/]+/', '-',
          preg_replace('/([a-z\d])([A-Z])/', '\1_\2',
              preg_replace('/([A-Z]+)([A-Z][a-z])/', '\1_\2',
                  preg_replace('/::/', '/', $text)))));

      return trim($text, '-');
  }

  /**
   * @static Используя PhpThumb генерирует превьюшку с заданными
   * @param  $file путь к файлу
   * @param array $dimentions массив(ширина, высота)
   * @return bool|string путь к превьюшке
   */
  public static function doResize($file, $dimentions) {

    $webDir = sfConfig::get('sf_web_dir', $_SERVER['SCRIPT_FILENAME']) . '/';
    $upDir = str_replace(strrchr($file, '/'), '', $file) . '/';
    $fileName = substr(strrchr($file, '/'), 1);

    $fileSize = is_file($webDir.$file) ? filesize($file) : 0;

    $ext = strrchr($fileName, '.');
    $fileName = str_replace($ext, '', $fileName);

    if (is_file($webDir.$upDir.implode('x', $dimentions).'/'.$fileName.$fileSize.$ext)) {
      return '/' . $upDir.implode('x', $dimentions).'/'.$fileName.$fileSize.$ext;
    }

    try {

      if (is_file($webDir.$file)) {
        $img = PhpThumbFactory::create($webDir.$upDir.$fileName.$ext);
      }
      if (!file_exists($webDir.$upDir.implode('x', $dimentions)).'/') {
        @mkdir($upDir.implode('x', $dimentions), null, true);
      }

      @$img && $img
        ->adaptiveResize($dimentions[0],$dimentions[1])
        ->save($webDir.$upDir.implode('x', $dimentions).'/'.$fileName.$fileSize.$ext);

    } catch (Exception $e) {
      return false;
    }

    return '/' . $upDir.implode('x', $dimentions).'/'.$fileName.$fileSize.$ext;

  }

    /**
     * @static
     * @param string $key to get
     * @param bool $success of get operation
     * @param null $default data or function with data return if not in cache
     * @return mixed|null
     */
    public static function apc_fetch($key, &$success, $default = null) {
      $has = null;
      $value = apc_fetch(sfConfig::get('sf_cache_dir') . '\\' . $key, $has);

      if (null !== $has) {
        $success = $has;
      } else {
        $success = $value !== false;
      }

      return $has ? $value : ($default instanceof Closure ? $default() : $default);
    }

  /**
   * @static
   * @param string $key to get
   * @param bool $success of get operation
   * @param null $default data if not in cache
   * @return mixed|null

  public static function apc_fetch_ns($key) {
    $names = self::apc_fetch('namespace_' . $key, $has, array());
//    var_dump($names);

    $r = array();
    foreach ($names as $key) {
      $res = self::apc_fetch($key, $has, false);

      if ($has && $res) {
        $r[$key] = $res;
      }
    }

    return $r;
  } */

  /**
   *
   * Сохранить $data в APC под значением $key
   *
   * @static
   * @param string $key to set
   * @param mixed $data to set
   * @param null $lifetime - lifetime in seconds
   * @param null $ns store key to namespace
   * @return bool success of storing
   */
  public static function apc_store($key, $data, $lifetime = null, $ns = null) {

    if ($ns !== null) {
      $names = self::apc_fetch('namespace_' . $ns, $has, array());


      $names[$key] = $key;

      self::apc_store('namespace_' . $ns, $names);
    }

    return apc_store(sfConfig::get('sf_cache_dir') . '\\' . $key, $data, $lifetime);

  }

  /**
   *
   * Удаление из кеша
   *
   * @static
   * @param  $key Ключ для удаления
   * @return bool|string
   */
  public static function apc_delete($key) {
    return apc_delete(sfConfig::get('sf_cache_dir') . '\\' . $key);
  }

  /**
   *
   * Удаление из кеша по всех записей по namespace
   * @static
   * @param  $ns
   * @return bool|string
   */
  public static function apc_delete_ns($ns) {

    $names = self::apc_fetch('namespace_' . $ns, $has, array());

    foreach ($names as $key) {
      self::apc_delete($key);
    }

    return self::apc_delete('namespace_' . $ns);

  }


/****
 * приватные переменные для конвертера числа в строку
 * @var bool
 */
  private static $converterInitialized = false;
  private static $billions = array('мільярд', 'мільярди', 'мільярдів');
  private static $millions = array('мільйон', 'мільйони', 'мільйонів');
  private static $thousands = array('тисяча', 'тисячі', 'тисяч');
  private static $hundreds = array('сто', 'двісті', 'триста', 'чотириста', "п'ятсот", 'шістсот', 'сімсот', 'вісімсот', "дев'ятсот");
  private static $tens = array('двадцять', 'тридцять', 'сорок', "п'ятдесят", 'шістдесят', 'сімдесят', 'вісімдесят', "дев'яносто");
  private static $tensUnit = array('десять', 'одинадцять', 'дванадцять', 'тринадцять', 'чотирнадцять', "п'ятнадцять", 'шістнадцять', 'сімнадцять', 'вісімнадцять', "дев'ятнадцять" );
  private static $units = array('один', 'два', 'три', 'чотири', "п'ять", 'шість', 'сім', 'вісім', "дев'ять");
  private static $unit = array('одна', 'дві');
  private static $mant = array('гривня', 'гривні', 'гривень'); // описания мантисс
  private static $expon = array('копійка', 'копійки', 'копійок'); // описания экспонент

  // функция возвращает необходимый индекс описаний разряда
  // ('миллион', 'миллиона', 'миллионов') для числа $ins
  // например для 29 вернется 2 (миллионов)
  // $ins максимум два числа
  private static function DescrIdx($ins) {
     if(intval($ins/10) == 1) // числа 10 - 19: 10 миллионов, 17 миллионов
     return 2;
     else
     {
        // для остальных десятков возьмем единицу
        $tmp = $ins%10;
        if($tmp == 1) // 1: 21 миллион, 1 миллион
        return 0;
        else if($tmp >= 2 && $tmp <= 4)
        return 1; // 2-4: 62 миллиона
        else
        return 2; // 5-9 48 миллионов
     }
  }

  // IN: $in - число,
  // $raz - разряд числа - 1, 1000, 1000000 и т.д.
  // внутри функции число $in меняется
  // $ar_descr - массив описаний разряда ('миллион', 'миллиона', 'миллионов') и т.д.
  // $fem - признак женского рода разряда числа (true для тысячи)
  private static function DescrSot(&$in, $raz, $ar_descr, $fem = false) {
     $ret = '';

     $conv = intval($in / $raz);
     $in %= $raz;

     $descr = $ar_descr[ self::DescrIdx($conv%100) ];

     if($conv >= 100)
     {
        $Sot = self::$hundreds;
        $ret = $Sot[intval($conv/100) - 1] . ' ';
        $conv %= 100;
     }

     if($conv >= 10)
     {
        $i = intval($conv / 10);
        if($i == 1)
        {
           $DesEd = self::$tensUnit;
           $ret .= $DesEd[ $conv - 10 ] . ' ';
           $ret .= $descr;
           // возвращаемся здесь
           return $ret;
        }
        $Des = self::$tens;
        $ret .= $Des[$i - 2] . ' ';
     }

     $i = $conv % 10;
     if($i > 0)
     {
        if( $fem && ($i==1 || $i==2) )
        {
           // для женского рода (сто одна тысяча)
           $Ed = self::$unit;
           $ret .= $Ed[$i - 1] . ' ';
        }
        else
        {
           $Ed = self::$units;
           $ret .= $Ed[$i - 1] . ' ';
        }
     }
     $ret .= $descr;
     return $ret;
  }


 /**
 * Dump symfony object
 * @static
 * @param $var
 * @param $name
 * @return string
 */
  public static function var_dump($var, $die = false, $name = null) {
    ob_start();
    print('<br/><pre>' . ($name !== null ? $name . ' :<br/>' : '' ));
    if (is_object($var) && get_class($var) == 'Doctrine_Query') {
      print_r($var->getSqlQuery());
    } elseif (is_object($var) && is_callable(array($var, 'toArray'))) {
      print_r($var->toArray());
    } else {
      print_r($var);
    }

    print('</pre></br>');
    $buffer = ob_get_contents();
    ob_end_clean();

    return $die ? die($buffer) : $buffer;
  }

  /**
   * Function that dumps an array or an object in the SF debug infos or
   * on s"\n"een/console
   *
   * @param $var mixed variable to dump
   * @param $die boolean Tells the function to stop the process or not
   *
   * @author Vernet Loic
   * @since  24 sept. 2006
   */
  public static function dump($var, $die = false, $name = null) {
    $d = self::var_dump($var, $die, $name);
    $dieMsg = $die ? self::traceText(1, 1) : self::traceHTML(1, 1);

    print($d);

    if ($die == true) {
      die($dieMsg);
    } else {
      print($dieMsg);
      sfWebDebug::getInstance()->logShortMessage($d . $dieMsg);
    }
  }

  public static function emailDump($var, $name = 'var') {
    $context= sfContext::getInstance();

    if (!$context->getMailer()) {
      return false;
    }



    $html = self::var_dump($var, false, $name) . self::traceHTML(2);
    $html .= self::formatArrayAsHtml('globals',  sfDebug::globalsAsArray());

    $message = Swift_Message::newInstance()
                    ->setFrom('send@nitralabs.com')
                    ->setTo('support@nitralabs.com')
                    ->setSubject(sfConfig::get('sf_root_dir') . '@' . $_SERVER['SERVER_NAME'] . '|'.$_SERVER['SERVER_ADDR'].' email stacktrace')
                    ->setBody($html, 'text/html')
                    ->attach(Swift_Attachment::newInstance(htmlspecialchars(sfYaml::dump(sfDebug::removeObjects(sfDebug::settingsAsArray())), ENT_QUOTES, sfConfig::get('sf_charset')), 'settings.yml', 'text/plain'))
                    ->attach(Swift_Attachment::newInstance(htmlspecialchars(sfYaml::dump(sfDebug::removeObjects(sfDebug::phpInfoAsArray())), ENT_QUOTES, sfConfig::get('sf_charset')), 'php_info.yml', 'text/plain'));

    $context->getMailer()->send($message);

  }

  static $traceId = 0;

  /**
   * Get HTML formatted backtrace
   * @static
   * @param int $ignoreCount
   * @return string
   */
  static public function traceHTML($ignoreCount = 1) {
    $result = "";
    self::$traceId++;
    $traceId = "pkSimpleBacktrace" . self::$traceId;
    $traceIdShow = $traceId . "Show";
    $traceIdHide = $traceId . "Hide";
    $result .= "<div class='pkSimpleBacktrace'>Trace " .
               '<a id="'.$traceIdShow.'" onclick="'. "document.getElementById('$traceId').style.display = 'block'; " .
                   "document.getElementById('$traceIdShow').style.display = 'none'; " .
                   "document.getElementById('$traceIdHide').style.display = 'inline'" .'">&gt;&gt;&gt;</a>'.
               '<a style="display: none" id="'.$traceIdHide.'" onclick="'. "document.getElementById('$traceId').style.display = 'none'; " .
                   "document.getElementById('$traceIdHide').style.display = 'none'; " .
                   "document.getElementById('$traceIdShow').style.display = 'inline'" .'">&lt;&lt;&lt;</a>';
    $result .= "</div>";
    $result .= "<pre id='$traceId' style='display: none'>\n";
    $result .= self::traceText($ignoreCount + 1);
    $result .= "</pre>\n";
    return $result;
  }

  /**
   * Get plaint text formatted backtrace
   * @static
   * @param int $ignoreCount
   * @return string
   */
  static public function traceText($ignoreCount = 1, $limit = null) {
    $trace = debug_backtrace();
    $count = 0;
    $result = "";
    $lastLine = 101;
    $limit = ($limit === null ? null : (int)$limit);

    foreach ($trace as $element)
    {
      $count++;
      if ($count > $ignoreCount) {
        $result .=
            "Class: " . (isset($element['class']) ? $element['class'] : 'NONE') . " function: " . $element['function'] .
            " line: " . $lastLine . "\n";
        if ($limit !== null && --$limit === 0) {
          break;
        }
      }
      $lastLine = isset($element['line']) ? $element['line'] : 0;
    }
    return $result;
  }

    /**
   * Converts an array to HTML.
   *
   * @param string $id     The identifier to use
   * @param array  $values The array of values
   *
   * @return string An HTML string
   */
  public static function formatArrayAsHtml($id, $values)
  {
    $id = ucfirst(strtolower($id));

    return '
    <h2>'.$id.'</h2>
    <div id="sfWebDebug'.$id.'" style="display: none"><pre>'.htmlspecialchars(sfYaml::dump(sfDebug::removeObjects($values)), ENT_QUOTES, sfConfig::get('sf_charset')).'</pre></div>
    ';
  }



}

